﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Okuma.CLDATAPI.Enumerations;
using System.Xml.Linq;
using System.Windows.Forms;
using OpenNETCF.MTConnect;
using OpenNETCF.IoC;

namespace Okuma
{
    public class OkumaConfiguration
    {
        private XDocument m_doc;
        private IAxis[] m_axes = null;
        private Program m_program;
        private Workpiece m_workpiece;
        private Spindle m_spindle;
        private Turret m_turret;
        private Tailstock m_tailstock;

        public SubSystemEnum SubSystem { get; private set; }
        public int RefreshPeriod { get; private set; }
        private ILogService Log { get; set; }

        private OkumaConfiguration(XDocument document)
        {
            Log = RootWorkItem.Services.Get<ILogService>();

            // set up defaults
            SubSystem = SubSystemEnum.NC_AL;
            RefreshPeriod = 1000;
            m_doc = document;
        }

        public static OkumaConfiguration FromXml(XDocument xml)
        {
            var config = new OkumaConfiguration(xml);

            try
            {
                var period = int.Parse(xml.Element("Configuration").Element("RefreshPeriod").Value);
                config.RefreshPeriod = period;
            }
            catch
            {
                // failure will result in the default setting
            }

            // load up the subsystem
            try
            {
                var type = (string)xml.Element("Configuration").Element("SubSystem").Attribute("type");
                var subsystem = (SubSystemEnum)Enum.Parse(typeof(SubSystemEnum), type, true);
                config.SubSystem = subsystem;
            }
            catch
            {
                // failure will result in the default setting
            }

            return config;
        }

        public IAxis[] Axes
        {
            get
            {
                // we must load this lazily becasue the CMacine must get built *and initialized* before we try creating CAxis objects
                // look for Axes
                if (m_axes == null)
                {
                    var axes = new List<IAxis>();

                    foreach (var axisElement in m_doc.Element("Configuration").Elements("Axis"))
                    {
                        try
                        {
                            var typestring = (string)axisElement.Attribute("type");
                            var type = (AllAxisIndexEnum)Enum.Parse(typeof(AllAxisIndexEnum), typestring, true);
                            axes.Add(ComponentFactory.CreateAxis(this.SubSystem, type, Log));
                        }
                        catch (Exception ex)
                        {
                            Log.Log(ex, "Okuma Adapter");
                        }
                    }
                    m_axes = axes.ToArray();
                }

                return m_axes;
            }
        }

        public Program Program
        {
            get
            {
                var programElement = m_doc.Element("Configuration").Element("Program");

                if (programElement != null)
                {
                    if (m_program == null)
                    {
                        m_program = new Program(this.SubSystem);
                    }
                }

                return m_program;
            }
        }

        public Workpiece Workpiece
        {
            get
            {
                var element = m_doc.Element("Configuration").Element("Workpiece");

                if (element != null)
                {
                    if (m_workpiece == null)
                    {
                        m_workpiece = new Workpiece(this.SubSystem);
                    }
                }

                return m_workpiece;
            }
        }

        public Spindle Spindle
        {
            get
            {
                var element = m_doc.Element("Configuration").Element("Spindle");

                if (element != null)
                {
                    if (m_spindle == null)
                    {
                        m_spindle = new Spindle(this.SubSystem);
                    }
                }

                return m_spindle;
            }
        }

        public Turret Turret
        {
            get
            {
                var element = m_doc.Element("Configuration").Element("Turret");

                if (element != null)
                {
                    if (m_turret == null)
                    {
                        m_turret = new Turret(this.SubSystem);
                    }
                }

                return m_turret;
            }
        }
        public Tailstock Tailstock
        {
            get
            {
                var element = m_doc.Element("Configuration").Element("Tailstock");

                if (element != null)
                {
                    if (m_tailstock == null)
                    {
                        m_tailstock = new Tailstock(this.SubSystem);
                    }
                }

                return m_tailstock;
            }
        }
    }

    internal static class ComponentFactory
    {
        static ComponentFactory()
        {
        }

        public static bool OnRealMachine
        {
            get
            {
                return true;
            }
        }

        public static IAxis CreateAxis(SubSystemEnum subSystem, AllAxisIndexEnum index, ILogService logService)
        {
            if (OnRealMachine)
            {
                return new Axis(subSystem, index, logService);
            }
            else
            {
                return new MockAxis(subSystem, index, logService);
            }
        }
    }

}
